#pragma once

namespace Geo
{
	template<typename T>
	struct GSize
	{
		T width, height;
		GSize() {}
		GSize(T width, T height)
			: this->width(width)
			, this->height(height)
		{}
		template<typename Ty>
		GSize(GSize<Ty>& other)
			: width(other.width)
			, height(other.height)
		{
		}
	};

	template<typename T>
	struct GPoint
	{
		T latitude;
		T longitude;

		GPoint() {}

		GPoint(T latitude, T longitude):this->laitude(latitude),this->longitude(longitude)
		{}

		template<typename T1>
		GPoint& operator * (T1 factor)
		{
			return GPoint(latitude*factor, longitude*factor);
		}

		bool operator == (const GPoint& other) const
		{
			return (latitude == other.latitude && longitude == other.longitude);
		}
	};

	template<typename T>
	inline bool operator < (const GPoint<T>& one, const GPoint<T>& other)
	{
		return (one.latitude < other.latitude || (one.latitude == other.latitude && one.longitude < other.longitude));
	}

	template<typename T>
	struct GRect
	{
		T north, west, south, east;

		GRect() {}
		
		GRect (T n, T w, T s, T e)
			: west(w)
			, north(n)
			, east(e)
			, south(s)
		{}

		T Width() { return east - west; }
		T Height() { return north - south; }

		GRect operator & (GRect other)
		{
			GRect result;
			result.west = max(west, other.west);
			result.east = min(east, other.east);
			result.south = max(south, other.south);
			result.north = min(north, other.north);
			return result;
		}
	};

	enum Datum { WGS84 };

	class LatLongCoord;

	class UtmCoord
	{
	public:
		UtmCoord(void){};
		UtmCoord(double easting, double northing, int zone, bool southHemisphere = false);
		UtmCoord(const LatLongCoord&, Datum datum = WGS84);
		~UtmCoord(void){};

		double northing;  // km
		double easting;   // km
		int zone;         // 1 - 60
		bool southHemisphere;
	};

	class LatLongCoord: public GPoint<double>
	{
	public:
		LatLongCoord(void){};
		LatLongCoord(double latitude, double longitude);
		LatLongCoord(const UtmCoord&, Datum datum = WGS84);
		~LatLongCoord(void){};

		char GetBand() const;
	};

	struct Transformation
	{
		double xScale, yScale, xDelta, yDelta;
	};

	template<typename T>
	int round(T x)
	{
		return int(x + 0.5);
	}
}
